package com.ruoyi.system.service.impl

import com.ruoyi.common.annotation.DataScope
import com.ruoyi.common.constant.UserConstants
import com.ruoyi.common.core.domain.entity.SysRole
import com.ruoyi.common.core.domain.entity.SysUser
import com.ruoyi.common.exception.ServiceException
import com.ruoyi.common.utils.MyStringUtils
import com.ruoyi.common.utils.SecurityUtils.userId
import com.ruoyi.common.utils.spring.SpringUtils
import com.ruoyi.system.domain.SysRoleDept
import com.ruoyi.system.domain.SysRoleMenu
import com.ruoyi.system.domain.SysUserRole
import com.ruoyi.system.mapper.SysRoleDeptMapper
import com.ruoyi.system.mapper.SysRoleMapper
import com.ruoyi.system.mapper.SysRoleMenuMapper
import com.ruoyi.system.mapper.SysUserRoleMapper
import com.ruoyi.system.service.ISysRoleService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.util.*

/**
 * 角色 业务层处理
 *
 * @author ruoyi
 */
@Service
open class SysRoleServiceImpl : ISysRoleService {
    @Autowired
    private lateinit var roleMapper: SysRoleMapper

    @Autowired
    private lateinit var roleMenuMapper: SysRoleMenuMapper

    @Autowired
    private lateinit var userRoleMapper: SysUserRoleMapper

    @Autowired
    private lateinit var roleDeptMapper: SysRoleDeptMapper

    /**
     * 根据条件分页查询角色数据
     *
     * @param role 角色信息
     * @return 角色数据集合信息
     */
    @DataScope(deptAlias = "d")
    override fun selectRoleList(role: SysRole?): List<SysRole> {
        return roleMapper.selectRoleList(role)
    }

    /**
     * 根据用户ID查询角色
     *
     * @param userId 用户ID
     * @return 角色列表
     */
    override fun selectRolesByUserId(userId: Long?): List<SysRole> {
        val userRoles = roleMapper.selectRolePermissionByUserId(userId)
        val roles = selectRoleAll()
        for (role in roles) {
            for (userRole in userRoles) {
                if (role.roleId == userRole.roleId) {
                    role.isFlag = true
                    break
                }
            }
        }
        return roles
    }

    /**
     * 根据用户ID查询权限
     *
     * @param userId 用户ID
     * @return 权限列表
     */
    override fun selectRolePermissionByUserId(userId: Long?): Set<String> {
        val perms = roleMapper.selectRolePermissionByUserId(userId)
        val permsSet: MutableSet<String> = HashSet()
        for (perm in perms) {
            if (MyStringUtils.isNotNull(perm)) {
                permsSet.addAll(mutableListOf(*perm.roleKey!!.trim { it <= ' ' }.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()))
            }
        }
        return permsSet
    }

    /**
     * 查询所有角色
     *
     * @return 角色列表
     */
    override fun selectRoleAll(): List<SysRole> {
        return SpringUtils.getAopProxy(this).selectRoleList(SysRole())
    }

    /**
     * 根据用户ID获取角色选择框列表
     *
     * @param userId 用户ID
     * @return 选中角色ID列表
     */
    override fun selectRoleListByUserId(userId: Long?): List<Long> {
        return roleMapper.selectRoleListByUserId(userId)
    }

    /**
     * 通过角色ID查询角色
     *
     * @param roleId 角色ID
     * @return 角色对象信息
     */
    override fun selectRoleById(roleId: Long?): SysRole? {
        return roleMapper.selectRoleById(roleId)
    }

    /**
     * 校验角色名称是否唯一
     *
     * @param role 角色信息
     * @return 结果
     */
    override fun checkRoleNameUnique(role: SysRole): Boolean {
        val roleId = if (MyStringUtils.isNull(role.roleId)) -1L else role.roleId
        val info = roleMapper.checkRoleNameUnique(role.roleName)
        return if (MyStringUtils.isNotNull(info) && info!!.roleId != roleId) {
            UserConstants.NOT_UNIQUE
        } else UserConstants.UNIQUE
    }

    /**
     * 校验角色权限是否唯一
     *
     * @param role 角色信息
     * @return 结果
     */
    override fun checkRoleKeyUnique(role: SysRole): Boolean {
        val roleId = if (MyStringUtils.isNull(role.roleId)) -1L else role.roleId
        val info = roleMapper.checkRoleKeyUnique(role.roleKey)
        return if (MyStringUtils.isNotNull(info) && info!!.roleId != roleId) {
            UserConstants.NOT_UNIQUE
        } else UserConstants.UNIQUE
    }

    /**
     * 校验角色是否允许操作
     *
     * @param role 角色信息
     */
    override fun checkRoleAllowed(role: SysRole) {
        if (MyStringUtils.isNotNull(role.roleId) && role.isAdmin) {
            throw ServiceException("不允许操作超级管理员角色")
        }
    }

    /**
     * 校验角色是否有数据权限
     *
     * @param roleId 角色id
     */
    override fun checkRoleDataScope(roleId: Long?) {
        if (!SysUser.isAdmin(userId)) {
            val role = SysRole()
            role.roleId = roleId
            val roles = SpringUtils.getAopProxy(this).selectRoleList(role)
            if (MyStringUtils.isEmpty(roles)) {
                throw ServiceException("没有权限访问角色数据！")
            }
        }
    }

    /**
     * 通过角色ID查询角色使用数量
     *
     * @param roleId 角色ID
     * @return 结果
     */
    override fun countUserRoleByRoleId(roleId: Long?): Int {
        return userRoleMapper.countUserRoleByRoleId(roleId)
    }

    /**
     * 新增保存角色信息
     *
     * @param role 角色信息
     * @return 结果
     */
    @Transactional
    override fun insertRole(role: SysRole): Int {
        // 新增角色信息
        roleMapper.insertRole(role)
        return insertRoleMenu(role)
    }

    /**
     * 修改保存角色信息
     *
     * @param role 角色信息
     * @return 结果
     */
    @Transactional
    override fun updateRole(role: SysRole): Int {
        // 修改角色信息
        roleMapper.updateRole(role)
        // 删除角色与菜单关联
        roleMenuMapper.deleteRoleMenuByRoleId(role.roleId)
        return insertRoleMenu(role)
    }

    /**
     * 修改角色状态
     *
     * @param role 角色信息
     * @return 结果
     */
    override fun updateRoleStatus(role: SysRole?): Int {
        return roleMapper.updateRole(role)
    }

    /**
     * 修改数据权限信息
     *
     * @param role 角色信息
     * @return 结果
     */
    @Transactional
    override fun authDataScope(role: SysRole): Int {
        // 修改角色信息
        roleMapper.updateRole(role)
        // 删除角色与部门关联
        roleDeptMapper.deleteRoleDeptByRoleId(role.roleId)
        // 新增角色和部门信息（数据权限）
        return insertRoleDept(role)
    }

    /**
     * 新增角色菜单信息
     *
     * @param role 角色对象
     */
    fun insertRoleMenu(role: SysRole): Int {
        var rows = 1
        // 新增用户与角色管理
        val list: MutableList<SysRoleMenu> = mutableListOf()
        for (menuId in role.menuIds) {
            val rm = SysRoleMenu()
            rm.roleId = role.roleId
            rm.menuId = menuId
            list.add(rm)
        }
        if (list.size > 0) {
            rows = roleMenuMapper.batchRoleMenu(list)
        }
        return rows
    }

    /**
     * 新增角色部门信息(数据权限)
     *
     * @param role 角色对象
     */
    fun insertRoleDept(role: SysRole): Int {
        var rows = 1
        // 新增角色与部门（数据权限）管理
        val list: MutableList<SysRoleDept> = mutableListOf()
        for (deptId in role.deptIds) {
            val rd = SysRoleDept()
            rd.roleId = role.roleId
            rd.deptId = deptId
            list.add(rd)
        }
        if (list.size > 0) {
            rows = roleDeptMapper.batchRoleDept(list)
        }
        return rows
    }

    /**
     * 通过角色ID删除角色
     *
     * @param roleId 角色ID
     * @return 结果
     */
    @Transactional
    override fun deleteRoleById(roleId: Long?): Int {
        // 删除角色与菜单关联
        roleMenuMapper.deleteRoleMenuByRoleId(roleId)
        // 删除角色与部门关联
        roleDeptMapper.deleteRoleDeptByRoleId(roleId)
        return roleMapper.deleteRoleById(roleId)
    }

    /**
     * 批量删除角色信息
     *
     * @param roleIds 需要删除的角色ID
     * @return 结果
     */
    @Transactional
    override fun deleteRoleByIds(roleIds: Array<Long>?): Int {
        if (roleIds != null) {
            for (roleId in roleIds) {
                checkRoleAllowed(SysRole(roleId))
                checkRoleDataScope(roleId)
                val role = selectRoleById(roleId)
                if (countUserRoleByRoleId(roleId) > 0) {
                    throw ServiceException(String.format("%1\$s已分配,不能删除", role!!.roleName))
                }
            }
        }
        // 删除角色与菜单关联
        roleMenuMapper.deleteRoleMenu(roleIds)
        // 删除角色与部门关联
        roleDeptMapper.deleteRoleDept(roleIds)
        return roleMapper.deleteRoleByIds(roleIds)
    }

    /**
     * 取消授权用户角色
     *
     * @param userRole 用户和角色关联信息
     * @return 结果
     */
    override fun deleteAuthUser(userRole: SysUserRole?): Int {
        return userRoleMapper.deleteUserRoleInfo(userRole)
    }

    /**
     * 批量取消授权用户角色
     *
     * @param roleId 角色ID
     * @param userIds 需要取消授权的用户数据ID
     * @return 结果
     */
    override fun deleteAuthUsers(roleId: Long?, userIds: Array<Long>?): Int {
        return userRoleMapper.deleteUserRoleInfos(roleId, userIds)
    }

    /**
     * 批量选择授权用户角色
     *
     * @param roleId 角色ID
     * @param userIds 需要授权的用户数据ID
     * @return 结果
     */
    override fun insertAuthUsers(roleId: Long?, userIds: Array<Long>?): Int {
        // 新增用户与角色管理
        val list: MutableList<SysUserRole> = mutableListOf()
        if (userIds != null) {
            for (userId in userIds) {
                val ur = SysUserRole()
                ur.userId = userId
                ur.roleId = roleId
                list.add(ur)
            }
        }
        return userRoleMapper.batchUserRole(list)
    }
}
